---
import { format } from "date-fns";

interface Props {
  data: object[];
  command: string;
  unit: string;
  competitor1: string;
  competitor2: string;
  competitor3: string;
  description: string;
  title: string;
  date: Date;
  higherIsBetter: boolean;
  system: string;
}

const { data, unit, competitor1, competitor2, competitor3 } = Astro.props;
---

<div
  data-slot="card"
  class="card px-0 rounded-xl flex flex-col overflow-hidden"
>
  <div
    data-slot="card-header"
    class="grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6 pb-2"
  >
    <div data-slot="card-title" class="leading-none font-semibold">
      <h3 class="text-lg">{Astro.props.title}</h3>
    </div>
    <div data-slot="card-description" class="text-muted-foreground text-sm">
      {Astro.props.description}
    </div>
  </div>
  <div data-slot="card-content" class="px-6 grow flex flex-col">
    <benchmark-chart-line
      data-props={JSON.stringify({
        data,
        unit,
        competitor1,
        competitor2,
        competitor3
      })}
      class="min-h-80 grow"
    >
      <!-- Had to use <div> elements for the chart to resize properly -->
      <div class="relative min-h-80 h-full w-full">
        <canvas></canvas>
      </div>
    </benchmark-chart-line>
    <div
      class="mt-4 text-center max-w-full prose prose-sm text-muted-foreground"
    >
      <p>
        {Astro.props.higherIsBetter ? "Higher is better" : "Lower is better"} | Benchmarks
        run on {Astro.props.system}, with the{" "}
        <code>{Astro.props.command}</code> command{
          Astro.props.date
            ? ` | Benchmarks performed on ${format(Astro.props.date, "MMMM d, yyyy")}`
            : ""
        }
      </p>
    </div>
  </div>
</div>

<script>
  import {
    LineController,
    LineElement,
    PointElement,
    Chart,
    CategoryScale,
    LinearScale,
    Legend,
    Tooltip,
    type ChartItem
  } from "chart.js";

  interface BenchmarkData {
    name: string;
    concurrency: string | number;
    ferron: string | number;
    competitor1: string | number;
    competitor2: string | number;
    competitor3: string | number;
  }

  Chart.register([
    LineController,
    LineElement,
    PointElement,
    CategoryScale,
    LinearScale,
    Legend,
    Tooltip
  ]);

  const style = getComputedStyle(document.body);
  const mutedForegroundColor = style.getPropertyValue("--muted-foreground");
  const borderColor = style.getPropertyValue("--border");
  const primaryColor = style.getPropertyValue("--primary");
  const chart1 = style.getPropertyValue("--chart-1");
  const chart2 = style.getPropertyValue("--chart-2");
  const chart3 = style.getPropertyValue("--chart-3");
  const fontFamily = style.getPropertyValue("--font-funnel-sans");

  class BenchmarkChart extends HTMLElement {
    connectedCallback() {
      const props = JSON.parse(this.dataset.props || "{}");
      const canvas = this.querySelector("canvas");
      Chart.defaults.font.family = fontFamily;
      Chart.defaults.font.size = 14;
      Chart.defaults.color = `hsla(${mutedForegroundColor}, 1)`;
      Chart.defaults.borderColor = `hsla(${borderColor}, 1)`;
      new Chart(canvas as ChartItem, {
        type: "line",
        data: {
          labels: props.data.map((item: BenchmarkData) => item.concurrency),
          datasets: [
            {
              label: "Ferron",
              data: props.data.map((item: BenchmarkData) => item.ferron),
              borderColor: `hsla(${primaryColor}, 1)`,
              backgroundColor: `hsla(${primaryColor}, 1)`,
              pointStyle: false
            },
            {
              label: props.competitor1,
              data: props.data.map((item: BenchmarkData) => item.competitor1),
              borderColor: `hsla(${chart1}, 1)`,
              backgroundColor: `hsla(${chart1}, 1)`,
              pointStyle: false
            },
            {
              label: props.competitor2,
              data: props.data.map((item: BenchmarkData) => item.competitor2),
              borderColor: `hsla(${chart2}, 1)`,
              backgroundColor: `hsla(${chart2}, 1)`,
              pointStyle: false
            },
            {
              label: props.competitor3,
              data: props.data.map((item: BenchmarkData) => item.competitor3),
              borderColor: `hsla(${chart3}, 1)`,
              backgroundColor: `hsla(${chart3}, 1)`,
              pointStyle: false
            }
          ]
        },
        options: {
          maintainAspectRatio: false,

          scales: {
            x: {
              title: {
                display: true,
                text: "Concurrent requests"
              }
            },
            y: {
              beginAtZero: true,
              title: {
                display: true,
                text: props.unit
              }
            }
          }
        }
      });
    }
  }

  customElements.define("benchmark-chart-line", BenchmarkChart);
</script>
